#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include "glm.h"
#include "texture.h"
#include <time.h>
#include <iostream>
using namespace std;
#define PI 3.14159

GLMmodel* pmodel = NULL;
GLfloat lightPos[4] = {0, 0, 50, -1.0}; //Position of the light source.
Texture treeTexture[10];
GLuint texture[10];
unsigned int dif;
static GLdouble angle;
static GLdouble startX;
bool mouseDown = false;
bool LoadTreeTextures()
{
    char filename[] = "obj/maps/texture0.tga";
    glGenTextures(10, texture);
    for(int i=0; i<10; i++){
        filename[16] = 48 + i;
        if (LoadTGA(&treeTexture[i], filename)){
            glBindTexture(GL_TEXTURE_2D, texture[i]);
            gluBuild2DMipmaps(GL_TEXTURE_2D, treeTexture[i].bpp / 8, treeTexture[i].width, treeTexture[i].height, treeTexture[i].type, GL_UNSIGNED_BYTE, treeTexture[i].imageData);
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);        
            if (treeTexture[i].imageData)
            {
                free(treeTexture[i].imageData); 
            }
        }
    }
    return true;
}

void loadmodel(void){
    if (!pmodel) {
    	pmodel = glmReadOBJ("obj/hth.obj");
    	if (!pmodel) exit(0);
    	glmUnitize(pmodel);
    	glmFacetNormals(pmodel);
    	glmVertexNormals(pmodel, 90.0);
    }
}
void drawmodel(int dif)
{
    int i = dif%10;
    glBindTexture(GL_TEXTURE_2D, texture[i]);
    glmDraw(pmodel, GLM_SMOOTH | GLM_TEXTURE);
}

void myInit( void )  {
    glClearColor (0.0, 0.0, 0.0, 0.0);
    glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_BLEND);
    glEnable(GL_TEXTURE_2D);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE);
    glShadeModel (GL_SMOOTH);
    LoadTreeTextures();
    loadmodel();
    dif = 0;
    angle = 0;
}
void sleep(unsigned timeout)
{
  timeout += clock();
  while(clock() < timeout) continue;
}

void myDisplay( void )  {
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glPushMatrix();
    drawmodel(dif);
}

//animation.
void animate()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    dif++;
    drawmodel(dif);
    glRotatef(angle,0,1,0);
    Sleep(40);
    glutSwapBuffers();
}

void  myKeyboard(unsigned char key, int x, int y){
    switch (key)
    {
    case 27:
    case 'q':
    case 'Q':
        exit(0);
        break;
    case 'd':
    case 'D':
        angle = -5;
        break;
    case 'a':
    case 'A':
        angle = 5;
        break;
    case 's':
    case 'S':
        angle = 0;
        break;
    case 'r':
    case 'R':
        glPopMatrix();
        glPushMatrix();
        break;
    }
}

void mouse(int button, int state, int x, int y){
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {
        mouseDown = true;
        startX = x;
        angle = 0;
    }
    else
        mouseDown = false;
}

void mouseMotion(int x, int y){
    if (mouseDown)
    {
        GLdouble change = (startX- x)/3;
        glRotatef(change,0,1,0);
        startX = x;
    }
}

/* ----------------------------------------------------------------------- */
/* Function    : int main( int argc, char** argv )
 *
 * Description : This is the main function. It sets up the rendering
 *               context, and then reacts to user events.
 *
 * Parameters  : int argc     : Number of command-line arguments.
 *               char *argv[] : Array of command-line arguments.
 *
 * Returns     : int : Return code to pass to the shell.
 */

int main( int argc, char *argv[] )  {
    glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(800, 600);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("Assignmet");
	glutDisplayFunc(myDisplay);
	glutIdleFunc(animate);
	glutKeyboardFunc(myKeyboard);
	glutMouseFunc( mouse );
	glutMotionFunc( mouseMotion );
	myInit();
	glutMainLoop();
}

/* ----------------------------------------------------------------------- */


